﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HWR_Ants.Classes
{
    public class Ant
    {
        private static readonly Random ro_Random = new Random();
        private double _Pheromones;
        private readonly List<City> ro_VisitedCities;
        private City _CurrentPosition;
        private double _TourValue;

        public Ant(City startPosition, double pheromones)
        {
            _CurrentPosition = startPosition;
            _Pheromones = pheromones;
            ro_VisitedCities = new List<City>();
            VisitedCities.Add(startPosition);
        }

        private static Random _Random 
        {
            get { return ro_Random; }
        }

        public IList<City> VisitedCities
        {
            get { return ro_VisitedCities; }
        }

        public City CurrentPosition
        {
            get { return _CurrentPosition; }
            set { _CurrentPosition = value; }
        }

        public double Pheromones
        {
            get { return _Pheromones; }
            set { _Pheromones = value; }
        }

        public double TourValue
        {
            get { return _TourValue; }
            set { _TourValue = value; }
        }

        public bool SearchTour()
        {
            _TourValue = 0.0;

            while (TravelOn())
            {
                ;
            }

            Road closing_road = CurrentPosition.Roads(VisitedCities.First());
            if (closing_road != null)
            {
                _TourValue += closing_road.Distance;
                return true;
            }
            return false;
        }

        private bool TravelOn()
        {
            City next_City = GetNextCity();
            if (next_City == null)
            {
                return false;
            }

            _CurrentPosition = next_City;
            TourValue += VisitedCities.Last().Roads(_CurrentPosition).Distance;
            VisitedCities.Add(_CurrentPosition);
            return true;
        }

        private City GetNextCity()
        {
            Dictionary<City, double> cityWeights = new Dictionary<City, double>();
            double sum_of_weights = 0.0;

            foreach (City city in _CurrentPosition.NeighbourCitys)
            {
                if (!VisitedCities.Contains(city))
                {
                    double weight = _CurrentPosition.Roads(city).WeighedValue;
                    cityWeights.Add(city, weight);
                    sum_of_weights += weight; 
                }
            }

            double rnd = _Random.NextDouble();
            double sum = 0.0;
            foreach (KeyValuePair<City,double> pair in cityWeights)
            {
                sum += pair.Value / sum_of_weights;
                if (sum >= rnd)
                    return pair.Key;
            }

            return null;
        }
    }
}
